{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# %load ../example_code/item_21.py\n",
    "#!/usr/bin/env python3\n",
    "\n",
    "# Copyright 2014 Brett Slatkin, Pearson Education Inc.\n",
    "#\n",
    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "#     http://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License.\n",
    "\n",
    "# Preamble to mimick book environment\n",
    "import logging\n",
    "from pprint import pprint\n",
    "from sys import stdout as STDOUT"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Too many args and confusing. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Example 1\n",
    "def safe_division(number, divisor, ignore_overflow,\n",
    "                  ignore_zero_division):\n",
    "    try:\n",
    "        return number / divisor\n",
    "    except OverflowError:\n",
    "        if ignore_overflow:\n",
    "            return 0\n",
    "        else:\n",
    "            raise\n",
    "    except ZeroDivisionError:\n",
    "        if ignore_zero_division:\n",
    "            return float('inf')\n",
    "        else:\n",
    "            raise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "# Example 2\n",
    "result = safe_division(1.0, 10**500, True, False)\n",
    "print(result)\n",
    "assert result is 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inf\n"
     ]
    }
   ],
   "source": [
    "# Example 3\n",
    "result = safe_division(1.0, 0, False, True)\n",
    "print(result)\n",
    "assert result == float('inf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Example 4\n",
    "def safe_division_b(number, divisor,\n",
    "                    ignore_overflow=False,\n",
    "                    ignore_zero_division=False):\n",
    "    try:\n",
    "        return number / divisor\n",
    "    except OverflowError:\n",
    "        if ignore_overflow:\n",
    "            return 0\n",
    "        else:\n",
    "            raise\n",
    "    except ZeroDivisionError:\n",
    "        if ignore_zero_division:\n",
    "            return float('inf')\n",
    "        else:\n",
    "            raise"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Can use keyword args, but there is no way to force it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Example 5\n",
    "assert safe_division_b(1.0, 10**500, ignore_overflow=True) is 0\n",
    "assert safe_division_b(1.0, 0, ignore_zero_division=True) == float('inf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Example 6\n",
    "assert safe_division_b(1.0, 10**500, True, False) is 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## We can force it using *. WONDERFUL!!\n",
    "The *\tsymbol\tin\tthe\targument\tlist\tindicates\tthe\tend\tof\tpositional\targuments\tand\tthe\tbeginning of\tkeyword-only\targuments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Example 7\n",
    "def safe_division_c(number, divisor, *,\n",
    "                    ignore_overflow=False,\n",
    "                    ignore_zero_division=False):\n",
    "    try:\n",
    "        return number / divisor\n",
    "    except OverflowError:\n",
    "        if ignore_overflow:\n",
    "            return 0\n",
    "        else:\n",
    "            raise\n",
    "    except ZeroDivisionError:\n",
    "        if ignore_zero_division:\n",
    "            return float('inf')\n",
    "        else:\n",
    "            raise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "safe_division_c() takes 2 positional arguments but 4 were given",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-5deed29051ad>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# Example 8\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0msafe_division_c\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m500\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: safe_division_c() takes 2 positional arguments but 4 were given"
     ]
    }
   ],
   "source": [
    "# Example 8\n",
    "safe_division_c(1.0, 10**500, True, False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Example 9\n",
    "safe_division_c(1.0, 0, ignore_zero_division=True)  # No exception\n",
    "try:\n",
    "    safe_division_c(1.0, 0)\n",
    "    assert False\n",
    "except ZeroDivisionError:\n",
    "    pass  # Expected"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Positional: (1, 2)\n",
      "Keyword:    {'foo': 'bar', 'stuff': 'meep'}\n"
     ]
    }
   ],
   "source": [
    "# Example 10\n",
    "def print_args(*args, **kwargs):\n",
    "    print('Positional:', args)\n",
    "    print('Keyword:   ', kwargs)\n",
    "\n",
    "print_args(1, 2, foo='bar', stuff='meep')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## In Python2, it's complicated, but doable. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Example 11\n",
    "def safe_division_d(number, divisor, **kwargs):\n",
    "    ignore_overflow = kwargs.pop('ignore_overflow', False)\n",
    "    ignore_zero_div = kwargs.pop('ignore_zero_division', False)\n",
    "    if kwargs:\n",
    "        raise TypeError('Unexpected **kwargs: %r' % kwargs)\n",
    "    try:\n",
    "        return number / divisor\n",
    "    except OverflowError:\n",
    "        if ignore_overflow:\n",
    "            return 0\n",
    "        else:\n",
    "            raise\n",
    "    except ZeroDivisionError:\n",
    "        if ignore_zero_div:\n",
    "            return float('inf')\n",
    "        else:\n",
    "            raise\n",
    "\n",
    "assert safe_division_d(1.0, 10) == 0.1\n",
    "assert safe_division_d(1.0, 0, ignore_zero_division=True) == float('inf')\n",
    "assert safe_division_d(1.0, 10**500, ignore_overflow=True) is 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "safe_division_d() takes 2 positional arguments but 4 were given",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-7d838ddbc24c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# Example 12\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0msafe_division_d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: safe_division_d() takes 2 positional arguments but 4 were given"
     ]
    }
   ],
   "source": [
    "# Example 12\n",
    "safe_division_d(1.0, 0, False, True)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "Unexpected **kwargs: {'unexpected': True}",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-14-26eb839a9523>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# Example 13\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0msafe_division_d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munexpected\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-12-b4a27a867988>\u001b[0m in \u001b[0;36msafe_division_d\u001b[0;34m(number, divisor, **kwargs)\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0mignore_zero_div\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'ignore_zero_division'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Unexpected **kwargs: %r'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      7\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mdivisor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: Unexpected **kwargs: {'unexpected': True}"
     ]
    }
   ],
   "source": [
    "# Example 13\n",
    "safe_division_d(0.0, 0, unexpected=True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
